﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Media.Animation;
using System.Windows.Threading;

namespace GraphosButtonTest
{
    /// <summary>
    /// Interaction logic for Expander.xaml
    /// </summary>
    public partial class Expander : UserControl
    {
        public Expander()
        {
            InitializeComponent();
            DataContext = this;
        }

        protected override void OnInitialized(EventArgs e)
        {
            base.OnInitialized(e);
            StackPanel panel = new StackPanel();
            TextBox textbox = new TextBox();
            textbox.Text = "Search";
            textbox.Background = Brushes.Transparent;
            panel.Children.Add(textbox);

            ListBox listbox = new ListBox();
            ScrollViewer.SetVerticalScrollBarVisibility(listbox, ScrollBarVisibility.Hidden);
            ScrollViewer.SetHorizontalScrollBarVisibility(listbox, ScrollBarVisibility.Hidden);
            listbox.ItemsSource = new List<string>() { "one", "two", "three", "four", "five", "sixteen is a long number" };
            listbox.Background = Brushes.Transparent;
            listbox.BorderBrush = Brushes.Transparent;

            panel.Children.Add(listbox);
            MainContent = panel;

            


        }





        public FrameworkElement MainContent
        {
            get { return (FrameworkElement)GetValue(MainContentProperty); }
            set { SetValue(MainContentProperty, value); }
        }
        public static readonly DependencyProperty MainContentProperty =
            DependencyProperty.Register("MainContent", typeof(FrameworkElement), typeof(Expander), new FrameworkPropertyMetadata(null));

        public bool IsOpen
        {
            get { return (bool)GetValue(IsOpenProperty); }
            set { SetValue(IsOpenProperty, value); }
        }
        public static readonly DependencyProperty IsOpenProperty =
            DependencyProperty.Register("IsOpen", typeof(bool), typeof(Expander), new FrameworkPropertyMetadata(false, FrameworkPropertyMetadataOptions.AffectsMeasure));

        public bool IsClosed
        {
            get { return (bool)GetValue(IsClosedProperty); }
            set { SetValue(IsClosedProperty, value); }
        }
        public static readonly DependencyProperty IsClosedProperty =
            DependencyProperty.Register("IsClosed", typeof(bool), typeof(Expander), new FrameworkPropertyMetadata(true, FrameworkPropertyMetadataOptions.AffectsMeasure));

        public FrameworkElement ButtonContent
        {
            get { return (FrameworkElement)GetValue(ButtonContentProperty); }
            set { SetValue(ButtonContentProperty, value); }
        }
        public static readonly DependencyProperty ButtonContentProperty =
            DependencyProperty.Register("ButtonContent", typeof(FrameworkElement), typeof(Expander), new FrameworkPropertyMetadata(null));



        public State State
        {
            get { return (State)GetValue(StateProperty); }
            set { SetValue(StateProperty, value); }
        }

        // Using a DependencyProperty as the backing store for State.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty StateProperty =
            DependencyProperty.Register("State", typeof(State), typeof(Expander), new UIPropertyMetadata(State.Closed));



        protected override void OnMouseEnter(MouseEventArgs e)
        {
            base.OnMouseEnter(e);
            if (MainContent == null)
                return;

            if (State == (State.Closing | State.Open))
            {
                State = State.Opening;
                Open(0.25);
            }
            else if (State == State.Closing)
            {
                State = State.Opening;
                Open(0.5);
            }
        }


        protected override void OnMouseLeave(MouseEventArgs e)
        {
            base.OnMouseLeave(e);
            if (MainContent == null)
                return;

            if (State == State.Open)
            {
                State = State | State.Closing;
                Close(1.0, 0.5);
            }
            else if (State == State.Opening)
            {
                State = State.Closing;
                Close(0.5, 0.0);
            }
        }

        private void MainButton_Click(object sender, RoutedEventArgs e)
        {
            if (MainContent != null && State == State.Closed)
            {
                m_closedSize = new Size(ActualWidth, ActualHeight);
                State = State.Opening;
                Open(0.5);
            }
        }

        private void Open(double seconds)
        {

            MainContent.Measure(new Size(MaxWidth, MaxHeight));


            m_openAnim.Completed -= OpenAnimation_Completed;
            m_openAnim.Duration = TimeSpan.FromSeconds(seconds);
            m_openAnim.DecelerationRatio = 0.75;
            m_openAnim.AccelerationRatio = 0.25;

            m_openAnim.To = MainContent.DesiredSize.Width;
            BeginAnimation(WidthProperty, m_openAnim);

            m_openAnim.To = MainContent.DesiredSize.Height;
            BeginAnimation(HeightProperty, m_openAnim);

            m_openAnim.To = 1.0;
            MainContentControl.BeginAnimation(ContentControl.OpacityProperty, m_openAnim);

            m_openAnim.To = 0.0;
            m_openAnim.Completed += new EventHandler(OpenAnimation_Completed);
            MainButtonControl.BeginAnimation(Button.OpacityProperty, m_openAnim);



            Panel.SetZIndex(MainButtonControl, 0);
            Panel.SetZIndex(MainContentControl, 1);
        }

        void OpenAnimation_Completed(object sender, EventArgs e)
        {
            if (State == State.Opening)
                State = State.Open;
        }
        void CloseAnimation_Completed(object sender, EventArgs e)
        {
            if ((State & State.Closing) == State.Closing)
                State = State.Closed;
        }
        private void Close(double total, double delay)
        {


            //DoubleAnimation anim = new DoubleAnimation();
            m_closeAnim.Completed -= CloseAnimation_Completed;
            

            m_closeAnim.To = 0.0;
            m_closeAnim.DecelerationRatio = 0.75;
            m_closeAnim.AccelerationRatio = 0.25;
            m_closeAnim.Duration = TimeSpan.FromSeconds(total + delay);
            m_closeAnim.BeginTime = TimeSpan.FromSeconds(0.0);
            MainContentControl.BeginAnimation(ContentControl.OpacityProperty, m_closeAnim);

            m_closeAnim.Duration = TimeSpan.FromSeconds(total);
            m_closeAnim.BeginTime = TimeSpan.FromSeconds(delay);

            m_closeAnim.DecelerationRatio = 0.001;
            m_closeAnim.AccelerationRatio = 0.999;

            m_closeAnim.To = 1.0;
            MainButtonControl.BeginAnimation(Button.OpacityProperty, m_closeAnim);

            
            
            m_closeAnim.To = m_closedSize.Width;
            BeginAnimation(WidthProperty, m_closeAnim);

            m_closeAnim.Completed += CloseAnimation_Completed;
            m_closeAnim.To = m_closedSize.Height;
            BeginAnimation(HeightProperty, m_closeAnim);

          
            Panel.SetZIndex(MainButtonControl, 1);
            Panel.SetZIndex(MainContentControl, 0);
        }

        private Size m_closedSize;
        private Size m_openedSize;
        DispatcherTimer m_closeTimer = new DispatcherTimer() { Interval = TimeSpan.FromSeconds(1.0) };


        private void NextState()
        {
            State = (State)((int)(State + 1) % 4);
        }
        private void NextActionState()
        {
            State = (State)((int)(State + 2) % 4);
        }

        private DoubleAnimation m_openAnim = new DoubleAnimation();
        private DoubleAnimation m_closeAnim = new DoubleAnimation();
        private DoubleAnimation m_fadeAnim = new DoubleAnimation();


    }
    [Flags]
    public enum State
    {
        Closed = 0,
        Opening = 2,
        Open = 4,
        Closing = 8,
    }
}
